#pragma once
#include <iostream>
#include "Common.hpp"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define FIFO_DEFAULT "named"
#define ERR_EXIT(M)\
do\
{\
    perror(M);\
    exit(EXIT_FAILURE);\
}while(0)

class NamedFifo
{
public:
    NamedFifo(std::string &&fifo = FIFO_DEFAULT)
        : _fifo(fifo)
    {
        umask(0);
        int n = mkfifo(_fifo.c_str(), 0666);
        if (n != 0)
        {
            ERR_EXIT("mkfifo");
        }
    }
    ~NamedFifo()
    {
        unlink(_fifo.c_str());
    }

private:
    std::string _fifo;
};

class FifoOper
{
public:
    FifoOper(int flag, std::string &&fifo = FIFO_DEFAULT)
        : _fifo(fifo)
    {
        _fd = open(_fifo.c_str(), flag);
        if(_fd == -1)
        {
            ERR_EXIT("open");
        }
    }
    void ContinueToWrite()
    {
        std::string message;
        while (true)
        {
            std::cout << "Enter your message# ";
            std::getline(std::cin, message);
            write(_fd, message.c_str(), message.size());
        }
    }
    void ContinueToRead()
    {
        char buffer[1024] = {0};
        int n;
        while ((n = read(_fd, buffer, sizeof(buffer) - 1)) > 0)
        {
            buffer[n] = 0;
            std::cout << "Client say: " << buffer << std::endl;
        }
        std::cout << "quit n: " << n << std::endl;
    }
    ~FifoOper()
    {
        close(_fd);
    }

private:
    std::string _fifo;
    int _fd;
};